import { applyMiddleware, connect, createStore, Provider } from './redux.jsx';
import { logger, promise, thunk } from './redux-middleware';
import { getAsyncData } from './mock';
import './App.scss';

const reducer = (state, action) => {
  if (action.type === 'updateUser') {
    return {
      ...state,
      user: {
        ...state.user,
        ...action.payload,
      },
    };
  }
  if (action.type === 'getAsyncData') {
    return {
      ...state,
      asyncData: {
        ...state.asyncData,
        ...action.payload,
      },
    };
  }
  return state;
};

const initState = {
  user: { name: 'Jack', age: 18 },
  group: {
    name: '前端组',
  },
};

// thunk
const fetchAsyncData = (dispatch) => {
  getAsyncData().then((payload) => dispatch({ type: 'getAsyncData', payload }));
};

const store = createStore(reducer, initState, applyMiddleware(logger, thunk, promise));

const mapStateToProps = (state) => ({ user: state.user });
const mapDispatchToProps = (dispatch) => ({ updateUser: (payload) => dispatch({ type: 'updateUser', payload }) });

const connectToUser = connect(mapStateToProps, mapDispatchToProps);

const User = connectToUser(({ user }) => {
  // const { user } = useSelector(mapStateToProps);
  console.log('User Render---------------------------------------');
  return (
    <>
      <h1>User Component</h1>
      <h2>{user.name}</h2>
      <h2>{user.age}</h2>
      <hr />
    </>
  );
});
const Child1 = connect((state) => ({ group: state.group }))(({ group }) => {
  console.log('Child1 Render---------------------------------------');
  return (
    <>
      <h1>Child 1</h1>
      <h1>{group.name}</h1>
      <hr />
    </>
  );
});
const Child2 = connect((state) => ({ asyncData: state.asyncData }))(({ asyncData, dispatch }) => {
  console.log('Child2 Render---------------------------------------');
  const loadAsyncData = () => {
    // dispatch(fetchAsyncData); // redux-thunk
    dispatch({ type: 'getAsyncData', payload: getAsyncData() }); // redux-promise
  };
  return (
    <>
      <h1>Child 2</h1>
      <h2>{asyncData?.name}</h2>
      <h2>{asyncData?.age}</h2>
      <button onClick={loadAsyncData}>获取异步数据</button>
      <hr />
    </>
  );
});
const Child3 = () => {
  console.log('Child3 Render---------------------------------------');
  return (
    <>
      <h1>Child 3</h1>
      <hr />
    </>
  );
};

const UserModify = connectToUser(({ user, updateUser }) => {
  return (
    <>
      <h1>UserModify Component</h1>
      <input type="text" value={user.name} onChange={(e) => updateUser({ name: e.target.value })} />
      <hr />
    </>
  );
});

export default function App() {
  return (
    <div className="App">
      <Provider store={store}>
        <User />
        <Child1 />
        <Child2 />
        <Child3 />
        <UserModify />
      </Provider>
    </div>
  );
}
